/* Copyright (c) 2009, Antonie Jovanoski
 *	
 * All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contact e-mail: Antonie Jovanoski <minimoog77@gmail.com>
 */

#include <QtDebug>
#include <QMessageBox>
#include "qtwitdget.h"
#include "userpassdialog.h"
#include "qtwitverifycredentials.h"

QTwitdget::QTwitdget(QWidget *parent)
	:	QWidget(parent), 
		m_friendsTimeline(new QTwitFriendsTimeline(this)),
		m_twitUpdate(new QTwitUpdate(this)),
		m_imageDownloader(new ImageDownloader(this)),
		m_graphicsScene(new QGraphicsScene(this))
{
	ui.setupUi(this);

	//read last used username
	QSettings settings("QTwitdget", "QTwitdget");
	m_username = settings.value("LastUsername").toString();

	//should be programmable
	m_maxStatuses = 40;

	connect(ui.userpassButton, SIGNAL(clicked()), SLOT(userpassButtonClicked()));
	connect(ui.updateButton, SIGNAL(clicked()), SLOT(updateButtonClicked()));
	connect(m_friendsTimeline, SIGNAL(finished()), SLOT(finishedFriendsTimeline()));
	connect(m_imageDownloader, SIGNAL(finished()), SLOT(finishedDownloadImages()));
	connect(ui.updateEdit, SIGNAL(overLimit(bool)), ui.updateButton, SLOT(setDisabled(bool)));
	connect(ui.updateEdit, SIGNAL(returnPressed()), ui.updateButton, SLOT(click()));

	ui.graphicsView->setScene(m_graphicsScene);

	ui.updateEdit->setLimit(140);

	m_layout = new QGraphicsLinearLayout(Qt::Vertical);
	m_form = new QGraphicsWidget;
	m_graphicsScene->addItem(m_form);
	
	m_form->setPos(0, 0);

	userpassButtonClicked();

	setupTrayIcon();
}

void QTwitdget::userpassButtonClicked()
{
	UserPassDialog upd(this);
	upd.setUsername(m_username);
	if(!m_username.isEmpty())
		upd.setPasswordEditFocut();

	if(QDialog::Accepted == upd.exec()){

		//verify credentials
		QTwitVerifyCredentials *vc = new QTwitVerifyCredentials;
		connect(vc, SIGNAL(finished(bool)), SLOT(finishedVerifying(bool)));
		vc->setUsername(upd.username());
		vc->setPassword(upd.password());
		m_verified = false;
		vc->verify();
		//block until is verified
		while(!m_verified) 
			qApp->processEvents();

		if(!m_userpassValid){
			delete vc;
			QMessageBox::warning(this, tr("Credentials error!"), tr("Username or password invalid"));
			return;
		}

		delete vc;

		setUserPass(upd.username(), upd.password());

		//store last used username
		QSettings settings("QTwitdget", "QTwitdget");
		settings.setValue("LastUsername", upd.username());

		//start update timer
		//TODO: What about "old timer"?
		QTimer *timer = new QTimer(this);
		connect(timer, SIGNAL(timeout()), SLOT(updateTimeline()));
		timer->start(60000);

		updateTimeline();
	}
}

void QTwitdget::updateTimeline()
{
	if(m_statuses.isEmpty())	//first time, no statuses
		m_friendsTimeline->update(QDateTime(), 0, 0, 0);
	else
		//get statuses more recent than last status 
		m_friendsTimeline->update(QDateTime(), m_statuses.at(0).id(), 0, 0);
}

void QTwitdget::setUserPass(const QString &username, const QString &password)
{
	m_friendsTimeline->setUsername(username);
	m_friendsTimeline->setPassword(password);
	m_twitUpdate->setUsername(username);
	m_twitUpdate->setPassword(password);
	m_username = username;
	m_password = password;
}

void QTwitdget::updateButtonClicked()
{
	if(!ui.updateEdit->toPlainText().isEmpty()){
		//trim to 140 characters
		QString updateText = ui.updateEdit->toPlainText().left(140);
		m_twitUpdate->setUpdate(updateText);
		ui.updateEdit->clear();
	}
}

void QTwitdget::finishedFriendsTimeline()
{
	QList<QTwitStatus> lastStatuses = m_friendsTimeline->getStatuses();

	if(lastStatuses.isEmpty())
		return;

	//prepend last statuses to statuses
	QListIterator<QTwitStatus> iter(lastStatuses);
	iter.toBack();
	while(iter.hasPrevious())
		m_statuses.prepend(iter.previous());

	//remove elements if number of statuses is bigger maxStatuses
	if(m_statuses.count() > m_maxStatuses){
		int n = m_statuses.count() - m_maxStatuses;
		m_statuses.erase(m_statuses.end() - n, m_statuses.end());
	}

	if(m_statuses.count() >= m_listProxyWidget.count()){
		int num = m_statuses.count() - m_listProxyWidget.count();

		for(int i = 0; i < num; ++i){
			StatusWidget *sw = new StatusWidget;
			QGraphicsProxyWidget *proxyWidget = m_graphicsScene->addWidget(sw);
			m_listProxyWidget.append(proxyWidget);
			m_layout->addItem(proxyWidget);
		}
	} 

	//build url image list for downloading
	QList<QUrl> urlsImages;
	foreach(const QTwitStatus& s, m_statuses){
		urlsImages << s.profileImageUrl();
	}

	//set status messages
	for(int i = 0; i < m_statuses.count(); ++i){
		StatusWidget *sw = static_cast<StatusWidget*>(m_listProxyWidget.at(i)->widget());
		sw->setText(m_statuses.at(i).text());
		sw->setScreenName(m_statuses.at(i).screenName());
		sw->setCreated(m_statuses.at(i).created());
	}

	//download/load images
	m_imageDownloader->downloadImages(urlsImages);

	m_form->setLayout(m_layout);

	//force resize
	QResizeEvent *resizeEvent = new QResizeEvent(size(), size());
	QCoreApplication::postEvent(this, resizeEvent);

}

void QTwitdget::finishedDownloadImages()
{
	QHash<QString, QImage> images = m_imageDownloader->getImages();

	for(int i = 0; i < m_statuses.count(); ++i){
		StatusWidget *sw = static_cast<StatusWidget*>(m_listProxyWidget.at(i)->widget());
		QImage img = images.value(m_statuses.at(i).profileImageUrl());
		sw->setProfileImagePixmap(QPixmap::fromImage(img));
	}
}

void QTwitdget::setupTrayIcon()
{
	minimizeAction = new QAction(tr("Mi&nimize"), this);
	connect(minimizeAction, SIGNAL(triggered()), SLOT(hide()));

	restoreAction = new QAction(tr("&Restore"), this);
	connect(restoreAction, SIGNAL(triggered()), SLOT(showNormal()));

	quitAction = new QAction(tr("&Quit"), this);
	connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));

	trayIconMenu = new QMenu(this);
	trayIconMenu->addAction(minimizeAction);
	trayIconMenu->addAction(restoreAction);
	trayIconMenu->addSeparator();
	trayIconMenu->addAction(quitAction);

	trayIcon = new QSystemTrayIcon(this);
	trayIcon->setIcon(QIcon(":/images/twitter_32.ico"));
	trayIcon->setContextMenu(trayIconMenu);
	trayIcon->show();

	connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
		SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
}

void QTwitdget::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
	switch(reason){
		case QSystemTrayIcon::Trigger:
		case QSystemTrayIcon::DoubleClick:
			showNormal();
			break;
		default:
			;
	}
}

void QTwitdget::finishedVerifying(bool valid)
{
	m_userpassValid = valid;

	m_verified = true;
}

void QTwitdget::resizeEvent(QResizeEvent *e)
{
	if(m_form){
		float sw = static_cast<float>(ui.graphicsView->viewport()->width());
		float sh = m_graphicsScene->itemsBoundingRect().height();

		//form width same as viewport width
		QRectF rf = m_form->geometry();
		rf.setWidth(sw);
		rf.setHeight(sh);
		m_form->setGeometry(rf);

		//scene rectangle: width same as width of viewport, height total height of StatusWidgets
		m_graphicsScene->setSceneRect(0, 0, sw, sh);
	}

	QWidget::resizeEvent(e);
}

void QTwitdget::closeEvent(QCloseEvent *e)
{
	hide();
	e->ignore();
}